import pylab as _pylab
import numpy as _numpy
import time as _time
import wx as _wx
class GaelInput(object):
  """
  Class that create a callable object to retrieve mouse click in a
  blocking way, a la MatLab. Based on Gael Varoquaux's almost-working
  object. Thanks Gael! I've wanted to get this working for years!

  -Jack
  """

  debug  = True
  cid    = None   # event connection object
  clicks = []     # list of click coordinates
  n      = 1      # number of clicks we're waiting for
  lines  = False   # if we should draw the lines

  def on_click(self, event):
    """
    Event handler that will be passed to the current figure to
    retrieve clicks.
    """

    # write the debug information if we're supposed to
    if self.debug:
      print ("button "+str(event.button)+":"+str(event.xdata)+
             ", "+str(event.ydata))
      
    # if this event's a right click we're done
    if event.button == 3:
      self.done = True
      return

    # if it's a valid click (and this isn't an extra event
    # in the queue), append the coordinates to the list
    if event.inaxes and not self.done:
      self.clicks.append([event.xdata, event.ydata])

      # now if we're supposed to draw lines, do so
      if self.lines and len(self.clicks) > 1:
        event.inaxes.plot([self.clicks[-1][0], self.clicks[-2][0]],
                          [self.clicks[-1][1], self.clicks[-2][1]],
                          color='w', linewidth=2.0,scalex=False,
                          scaley=False)
        event.inaxes.plot([self.clicks[-1][0], self.clicks[-2][0]],
                          [self.clicks[-1][1], self.clicks[-2][1]],
                          color='k', linewidth=1.0,scalex=False,
                          scaley=False)
        _pylab.draw()

      # if we have n data points, we're done
      if len(self.clicks) >= self.n and self.n is not 0:
        self.done = True
        return


  def __call__(self, n=1, timeout=0, debug=False, lines=False):
    """
    Blocking call to retrieve n coordinate pairs through mouse clicks.
    
    n=1             number of clicks to collect. Set n=0 to keep collecting
                    points until you click with the right mouse button.
    timeout=30      maximum number of seconds to wait for clicks before
                    giving up. timeout=0 to disable
    debug=False     show each click event coordinates
    lines=False     draw lines between clicks
    """

    # just for printing the coordinates
    self.debug = debug

    # for drawing lines
    self.lines = lines

    # connect the click events to the on_click function call
    self.cid = _pylab.connect('button_press_event', self.on_click)

    # initialize the list of click coordinates
    self.clicks = []

    # wait for n clicks
    self.n    = n
    self.done = False
    t         = 0.0
    while not self.done:
      # key step: yield the processor to other threads
      _wx.Yield();
      _time.sleep(0.1)

      # check for a timeout
      t += 0.1
      if timeout and t > timeout: print "ginput timeout"; break;

    # All done! Disconnect the event and return what we have
    _pylab.disconnect(self.cid)
    self.cid = None
    return _numpy.array(self.clicks)



def ginput(n=1, timeout=0, show=True, lines=True):
  """
  Simple functional call for physicists. This will wait for n clicks
  from the user and return a list of the coordinates of each click.

  n=1             number of clicks to collect
  timeout=30      maximum number of seconds to wait for clicks
                  before giving up. timeout=0 to disable
  show=True       print the clicks as they are received
  lines=False     draw lines between clicks
  """

  x = GaelInput()
  return x(n, timeout, show, lines)
